package com.navinfo.platform.trip.common.arithmetic;

import com.navinfo.platform.trip.common.arithmetic.annotation.Arithmetic;
import com.navinfo.platform.trip.common.arithmetic.data.CommonData;
import com.navinfo.platform.trip.common.arithmetic.data.OuterEventData;
import com.navinfo.platform.trip.common.arithmetic.data.OuterStatisticData;
import com.navinfo.platform.trip.common.arithmetic.manager.EventConvert;
import com.navinfo.platform.trip.common.arithmetic.var.VarSpeedOver120;
import com.navinfo.platform.trip.common.arithmetic.enums.EventStatus;
import com.navinfo.platform.trip.common.arithmetic.enums.EventType;
import com.navinfo.platform.trip.common.arithmetic.exception.RangeAssert;
import com.navinfo.platform.trip.common.arithmetic.manager.AbstractArithmetic;
import com.navinfo.platform.trip.common.config.ConfigMap;
import com.navinfo.platform.trip.common.util.ArithmeticUtils;

import java.util.Optional;

/**
 * 超速120算法.<br>
 * 依赖{@link Mileage}里程油耗算法<br/>
 * 输出：统计<br/>
 */
@Arithmetic(name = "超速120算法")
public class SpeedOver120 extends AbstractArithmetic<VarSpeedOver120> {
    /**
     * 超速阀值，单位120KM/H
     */
    private int speedThreshold = ConfigMap.getInteger("SpeedOver120_Speed_Threshold");
    /**
     * 超速120KM/H时长阀值,单位ms
     */
    private long timeThreshold = ConfigMap.getLong("SpeedOver120_Time_Threshold");

    private boolean isOverSpeed(double speedKMH) {
        return speedKMH >= speedThreshold;
    }

    @Override
    public void calculate() {
        logger.debug("进入超速120算法.");
        VarSpeedOver120 var = getObj();
        CommonData commonData = getCommonData();
        int speedKmh = commonData.getSpeedKmh();

        //1.速度有效性判断
        RangeAssert.speedKmhIsInTheRange(speedKmh);

        //2.上一次和本次的超速状态
        boolean preIsOverSpeed = var.isPreOverSpeed();
        boolean curIsOverSpeed = isOverSpeed(speedKmh);
        logger.debug("超速120算法，超速状态：pre:{},current:{}", preIsOverSpeed, curIsOverSpeed);
        
        //3.算法计算
        EventStatus eventStatus = getEventStatus(preIsOverSpeed, curIsOverSpeed);
        switch (eventStatus){
            case START:
                logger.debug("超速120算法，事件开始.");
                OuterEventData eventData = EventConvert.convertStart(drivingData);
                eventData.setEvent(EventType.vehicleOverSpeed);
                var.setEvent(eventData);
                break;
            case IN:
                logger.debug("超速120算法，事件中.");
                Optional.ofNullable(var.getEvent()).ifPresent(event ->  EventConvert.convertCommonField(event, drivingData));
                break;
            case END:
                logger.debug("超速120算法，事件结束.");
                Optional.ofNullable(var.getEvent()).ifPresent(event ->  {
                    EventConvert.convertCommonField(event, drivingData);
                    endEvent();
                });
                break;
            default:
                break;
        }

        //4.最后一个点，判断是否有持续30秒的事件
        if (commonData.isTripLastNode()) {
            endEvent();
        }

        var.setPreOverSpeed(curIsOverSpeed);
        logger.debug("超速120算法结束.");
    }

    @Override
    public void collect(OuterStatisticData statisticDataOut) {
        VarSpeedOver120 varOverSpeed = super.getObj();
        statisticDataOut.setSo120Number(varOverSpeed.getNumber());
        statisticDataOut.setSo120Mileage(ArithmeticUtils.mileageMToM(varOverSpeed.getMileage()));
        statisticDataOut.setSo120Fuel(ArithmeticUtils.fuelMlToMl(varOverSpeed.getFuel()));
        statisticDataOut.setSo120Duration(ArithmeticUtils.timeMsToSecond(varOverSpeed.getDuration()));
    }

    /**
     * 处理事件的结束状态
     */
    private void endEvent() {
        VarSpeedOver120 var = getObj();
        Optional.ofNullable(var.getEvent()).ifPresent(eventData ->{
            EventConvert.convertEnd(eventData, drivingData);
            if (Optional.ofNullable(eventData.getDuration()).orElse(0L) >= timeThreshold) {
                //事件结束，统计里程、油耗、时长、次数加1
                eventDataToVar(eventData);
            }

            //清空事件变量
            var.setEvent(null);

            //设置上个点的状态，供下个点使用
            var.setPreOverSpeed(false);
        });
    }

    /**
     * 事件数据赋值到统计数据中
     * @param eventData
     */
    private void eventDataToVar(OuterEventData eventData){
        VarSpeedOver120 varOverSpeed = super.getObj();

        //事件结束，统计里程、油耗、时长、次数加1
        varOverSpeed.setNumber(varOverSpeed.getNumber() + 1);
        varOverSpeed.addMileage( Optional.ofNullable(eventData.getExtendField05()).orElse(0.0));
        varOverSpeed.addFuel( Optional.ofNullable(eventData.getExtendField06()).orElse(0.0));
        varOverSpeed.addDuration( Optional.ofNullable(eventData.getDuration()).orElse(0L).intValue());;
    }
}
